package cn.lyjuan.archetypes.bms.web.controller.base;


import cn.lyjuan.archetypes.bms.web.bean.vo.BaseResp;
import cn.lyjuan.archetypes.bms.web.util.NumberUtils;
import cn.lyjuan.archetypes.bms.web.bean.vo.PagerResp;
import cn.lyjuan.archetypes.bms.web.property.SysProperties;
import cn.lyjuan.archetypes.bms.web.util.AppUtils;
import cn.lyjuan.archetypes.bms.web.util.SpringUtils;
import com.github.pagehelper.Page;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ly on 2015/1/12.
 */
public class BaseController
{
    private static Logger log = LogManager.getLogger(BaseController.class.getName());

    @Autowired
    protected SysProperties sysProperties;

    /**
     * 得到request对象
     */
    public HttpServletRequest req()
    {
        return AppUtils.req();
    }

    public HttpServletResponse resp()
    {
        return AppUtils.res();
    }

    public String param(String key)
    {
        String param = req().getParameter(key);
        if (null == param || "".equals(param.trim()))
            return null;

        return param.trim();
    }

    /**
     * 返回相应页面
     * @param view
     * @return
     */
    public ModelAndView mv(String view)
    {
        return new ModelAndView(view);
    }

    /**
     * 返回相应页面，同里将数据以 {@code data} 为key，携带在 request attribute中。
     * @param view
     * @param resp
     * @return
     */
    public ModelAndView mv(String view, BaseResp resp)
    {
        ModelAndView mv = mv(view);
        mv.addObject("data", resp);
        return mv;
    }

    /**
     * 返回一个空 ModelAndView，此时可自响应 reponse 数据，但需要注意：如果自响应数据，
     * Spring 并不会处理响应的 contenxt-type，因为自响应时，Spring拿不到数据
     * @return
     */
    public ModelAndView mv()
    {
        return new ModelAndView();
    }

    public ServletOutputStream out()
    {
        ServletOutputStream out = null;
        try
        {
            out = resp().getOutputStream();
        } catch (IOException e)
        {
            log.error("get output stream error", e);
        }
        return out;
    }




    /**
     * 整合 GET 和 POST 请求，若有重复， GET 参数会被覆盖
     *
     * @return
     * @throws IOException
     */
    protected Map<String, String> paramsToMap()
    {
        HttpServletRequest req = SpringUtils.getRequest();
        // GET
        Map<String, String> getParams = new HashMap<String, String>();

        Enumeration<String> names = req.getParameterNames();

        if (null == names) return getParams;

        String name = null;
        String value = null;
        while (names.hasMoreElements())
        {
            name = names.nextElement();

            if (StringUtils.isEmpty(name)) continue;

            value = req.getParameter(name);

            getParams.put(name, value);
        }

        return getParams;
    }

    /**
     * 获取 DWZ 后台当前页参数
     *
     * @return
     */
    public int getPn()
    {
        String pn = SpringUtils.getRequest().getParameter(sysProperties.getPageNumName());

        return NumberUtils.isNumber(pn) ? Integer.parseInt(pn) : 1;
    }

    /**
     * 获取 DWZ 后台页大小参数
     *
     * @return
     */
    public int getPs()
    {
        String ps = SpringUtils.getRequest().getParameter(sysProperties.getPageSizeName());
        return NumberUtils.isNumber(ps) ? Integer.parseInt(ps) : sysProperties.getPageSizeDef();
    }

    /**
     * 向 response 输出信息
     *
     * @param outMsg
     */
    public void out(String outMsg)
    {
        AppUtils.resp(outMsg);
    }

    /**
     * 响应成功JSON
     */
    public void respBmsSucc()
    {
        AppUtils.respJson(BaseResp.resp());
    }

    public void respBmsSucc(Object obj)
    {
        BaseResp resp = BaseResp.resp(obj);

        AppUtils.respJson(resp);
    }

    /**
     * 封装分页信息
     *
     * @param list
     */
    public void pkgPage(List list)
    {
        if (!(list instanceof Page))
            return;

        Page page = (Page) list;

        PagerResp pagerResp = PagerResp.page(page.getPageNum(), page.getPageSize(), page.getTotal());

        req().setAttribute(sysProperties.getPageName(), pagerResp);
    }

    /**
     * 封装响应数据到{@code model}中，所有数据以 data key 包含
     * @param data      主数据以data.data包含
     * @param others     其他数据自定义名称，以键值对方式 key1, val1, key2, val2...， key只能为{@code String}
     */
    public void pkgData(Model model, Object data, Object... others)
    {
        Map<String, Object> map = new HashMap<>();
        if (null != data)
            map.put("data", data);

        if (null != others && others.length > 2)
        {
            // 如果数组数量为奇数，则最后一位不包含，所有这里在用 length-1
            for (int i = 0; i < others.length-1; i+=2)
            {
                map.put((String) others[i], others[i + 1]);
            }
        }

        model.addAttribute("data", map);
    }

    /**
     * 封装响应数据，此方法将所有数据打包放入 {@code PagerResp}的 data 属性中
     * @param data         主数据以 PagerResp.data.data 为key
     * @param others    其他数据以 PagerResp.data.otherkey 包含
     * @return
     */
    public PagerResp pkgData(Object data, Object...others)
    {
        Map<String, Object> map = new HashMap<>();
        if (null != data)
            map.put("data", data);

        if (null != others && others.length > 2)
        {
            // 如果数组数量为奇数，则最后一位不包含，所有这里在用 length-1
            for (int i = 0; i < others.length-1; i+=2)
            {
                map.put((String) others[i], others[i + 1]);
            }
        }

        // 封装分页信息后中，重新设置 data 数据为 map
        PagerResp pager = BaseResp.resp(data);
        pager.setData(map);

        return pager;
    }
}
